package com.zx.common.utils;

import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.concurrent.TimeUnit;

/**
 * -- 高贵的马儿驱逐体内的一切外力 --
 *
 * @author kaajee
 * @date 2025/9/6
 * @desc 编号生成器
 */
@Component
public class RedisSequenceGenerator {

    // 日期格式：年月日
    private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyyMMdd");

    // Redis中存储序号的键前缀
    private static final String REDIS_KEY_PREFIX = "sequence:";

    // 序号过期时间（24小时），确保每天自动重置
    private static final long EXPIRATION_HOURS = 24;

    private final StringRedisTemplate stringRedisTemplate;

    // 构造函数注入Redis模板
    public RedisSequenceGenerator(StringRedisTemplate stringRedisTemplate) {
        this.stringRedisTemplate = stringRedisTemplate;
    }

    /**
     * 生成编号
     * @param prefix 前缀，如"REC"
     * @return 生成的编号，格式为：前缀-年月日-序号（3位）
     */
    public String generateSequence(String prefix) {
        // 获取当前日期字符串
        String dateStr = LocalDate.now().format(DATE_FORMATTER);
        // 构建Redis键（格式：sequence:REC:20240303）
        String redisKey = REDIS_KEY_PREFIX + prefix + ":" + dateStr;

        // 使用Redis的INCR命令实现原子自增，确保线程安全和分布式环境下的唯一性
        Long sequence = stringRedisTemplate.opsForValue().increment(redisKey);

        // 设置过期时间（只在首次设置时生效）
        if (sequence != null && sequence == 1) {
            stringRedisTemplate.expire(redisKey, EXPIRATION_HOURS, TimeUnit.HOURS);
        }

        // 格式化序号为3位数字
        String sequenceStr = String.format("%03d", sequence);

        // 组合成最终编号
        return String.format("%s-%s-%s", prefix, dateStr, sequenceStr);
    }

    /**
     * 重置指定前缀当天的序号
     * @param prefix 前缀
     */
    public void resetTodaySequence(String prefix) {
        String dateStr = LocalDate.now().format(DATE_FORMATTER);
        String redisKey = REDIS_KEY_PREFIX + prefix + ":" + dateStr;
        stringRedisTemplate.delete(redisKey);
    }

    /**
     * 重置指定前缀和日期的序号
     * @param prefix 前缀
     * @param date 日期
     */
    public void resetSequence(String prefix, LocalDate date) {
        String dateStr = date.format(DATE_FORMATTER);
        String redisKey = REDIS_KEY_PREFIX + prefix + ":" + dateStr;
        stringRedisTemplate.delete(redisKey);
    }
}
